//@include lib_Class.js
//@include lib_sol.common.ObjectUtils.js
//@include lib_sol.common.Cache.js
/*
* Local definition of the class `sol.common.Cache` for backward compatibility of previous solution packages.
*/
if (!sol.ClassManager.getClass("sol.common.Cache")) {
sol.define("sol.common.Cache", {
initialize: function (config) {
var me = this;
me.cache = new java.util.concurrent.ConcurrentHashMap(8, 0.9, 1);
},
/**
* Inserts the specified key-value pair into the cache.
* @param {String} key
* @param {Object} value
* @return {Object} The previous value associated with the key, or null if there was no mapping before
*/
put: function (key, value) {
var me = this;
return me.cache.put(key, value);
},
/**
* Inserts all key-value pairs specified by an object into the cache. Existing mappings will be replaced.
* @param {Object} data Property names will be used as keys and the associated values as values.
*/
putAll: function (data) {
var me = this;
me.cache.putAll(data);
},
/**
* Tests if the specified object is a key in the cache.
* @param {String} key
* @return {Boolean}
*/
containsKey: function (key) {
var me = this;
return me.cache.containsKey(key);
},
/**
* Returns the value for the specified key from the cache, or null if the chache contains no mapping for the key.
* @param {String} key
* @return {Object}
*/
get: function (key) {
var me = this;
return me.cache.get(key);
},
/**
* Returns an enumeration of all keys in the cache.
* @return {Object} An `java.util.Enumeration` of all keys
*/
keys: function () {
var me = this;
return me.cache.keys();
},
/**
* Returns a collection view of the values contained in the cache.
* @return {Object} An `java.util.Collection` of all values
*/
values: function () {
var me = this;
return me.cache.values();
},
/**
* Returns an enumeration of the values in the cache.
* @return {Object} An `java.util.Enumeration` of all values
*/
elements: function () {
var me = this;
return me.cache.elements();
},
/**
* Removes the key (and its corresponding value) from the cache.
* @param {String} key
* @return {Object} The previous value associated with the key, or null if there was no value for the key
*/
remove: function (key) {
var me = this;
return me.cache.remove(key);
},
/**
* Returns the number of key-value pairs in the cache.
* @return {Number}
*/
size: function () {
var me = this;
return me.cache.size();
},
/**
* Returns `true` if the chache contains no key-value pairs.
* @return {Boolean}
*/
isEmpty: function () {
var me = this;
return me.cache.isEmpty();
},
/**
* Removes all of the mappings from the cache.
*/
clear: function () {
var me = this;
me.cache.clear();
}
});
}
/**
* Cache for Translate Terms. This class handles localization in Business Solutions.
*
* Property files should be placed in `Administration\Localization\`.
*
* ELO internal projects must use `Administration\Localization\system`. Modifications and Partner implementations must
* use `Administration\Localization\custom`.
*
* # Using localization in scripts
*
* Thanks to a require function call all required translation terms will get loaded in the cache. This must be done
* before terms are used by scripts. Following example shows a common usage for a dynamic keyword list.
*
* A property file must be located in the localization folder. e.g. `Administration\Localization\system\sol.invoice.locale.properties`
*
* sol.invoice.dynkwl.Company.ID=Company id
* sol.invoice.dynkwl.Company.NAME=Company name
* sol.invoice.dynkwl.Company.CITY=City
*
* The TranslateTerms utilizes the use of translation keys.
*
* sol.common.TranslateTerms.require('sol.invoice.dynkwl.Company');
*
* var tableHeaders = [
* sol.common.TranslateTerms.translate('sol.invoice.dynkwl.Company.ID'),
* sol.common.TranslateTerms.translate('sol.invoice.dynkwl.Company.NAME'),
* sol.common.TranslateTerms.translate('sol.invoice.dynkwl.Company.CITY')];
*
* @author PZ, ELO Digital Office GmbH
* @version 1.03.000
*
* @eloix
* @eloas
*
* @requires sol.common.ObjectUtils
* @requires sol.common.Cache
*/
sol.define("sol.common.TranslateTerms", {
singleton: true,
/**
* Loads a list of translation keys by a given prefix.
* Prefixes can be either passed as an array or string.
* @param {String} prefixes
* @param {String} additionalLanguage (optional)
*/
require: function (prefixes, additionalLanguage) {
var me = this,
requestedCount, idx, findTranslateTermInfo, findResult, i, translateTerm, j, language, term;
me.logger.enter("require", arguments);
if (!prefixes) {
me.logger.warn("Translation term key prefix not set; use prefix 'sol'.");
prefixes = ["sol"];
}
if (!sol.common.ObjectUtils.isArray(prefixes)) {
prefixes = [prefixes];
}
requestedCount = prefixes.length;
me.getLangs(additionalLanguage);
prefixes = me.filterPrefixes(prefixes);
if (prefixes.length > 0) {
me.logger.debug(["Load {0} of {1} requested prefixes", requestedCount, prefixes.length]);
me.translateTerms = me.translateTerms || sol.create("sol.common.Cache");
try {
findTranslateTermInfo = new FindTranslateTermInfo();
findTranslateTermInfo.terms = prefixes;
findTranslateTermInfo.langs = me.languages;
idx = 0;
findResult = ixConnect.ix().findFirstTranslateTerms(findTranslateTermInfo, 100);
while (true) {
for (i = 0; i < findResult.translateTerms.length; i++) {
translateTerm = findResult.translateTerms[i];
for (j = 0; j < translateTerm.langs.length; j++) {
language = translateTerm.langs[j];
term = translateTerm.termLangs[j] || "";
if (!me.translateTerms.containsKey(language)) {
me.translateTerms.put(language, sol.create("sol.common.Cache"));
}
me.translateTerms.get(language).put(translateTerm.translationKey, term);
}
}
if (!findResult.moreResults) {
break;
}
idx += findResult.translateTerms.length;
findResult = ixConnect.ix().findNextTranslateTerms(findResult.searchId, idx, 100);
}
me.rememberPrefixes(prefixes);
} finally {
if (findResult) {
ixConnect.ix().findClose(findResult.searchId);
}
}
} else {
me.logger.debug("All prefixes have already been cached.");
}
me.logger.exit("require");
},
/**
* @private
* Retrieves the system languages
* @param {String} additionalLanguage (optional) Additional language
*/
getLangs: function (additionalLanguage) {
var me = this,
langsTerm, i, lang;
me.logger.enter("getLangs", arguments);
if (me.languages) {
me.addLang(additionalLanguage);
} else {
me.languages = [];
langsTerm = ixConnect.ix().checkoutTranslateTerms([TranslateTermC.GUID_SYSTEM_LANGUAGES], LockC.NO);
for (i = 0; i < langsTerm[0].langs.length; i++) {
lang = langsTerm[0].langs[i];
me.addLang(lang);
}
}
me.logger.exit("getLangs", me.languages);
},
/**
* @private
* Adds a language
* @param {String} language Language
*/
addLang: function (language) {
var me = this;
language = String(language || "");
if (language) {
if (me.languages.indexOf(language) < 0) {
me.languages.push(language);
delete me.downloadedPrefixes;
}
}
},
/**
* @private
* Checks which prefixes have already been loaded.
* @param {String[]} prefixes
* @return {String[]}
*/
filterPrefixes: function (prefixes) {
var me = this,
filteredCount = 0,
filtered;
if (me.downloadedPrefixes) {
filtered = [];
prefixes.forEach(function (prefix) {
if (!me.downloadedPrefixes.containsKey(String(prefix))) {
filtered.push(prefix);
} else {
filteredCount++;
}
});
} else {
filtered = prefixes;
}
me.logger.debug(["Filtered '{0}' prefixes that have already been loaded", filteredCount]);
return filtered;
},
/**
* @private
* Saves the prefixes that have been loaded, to avoid repeated requests.
* @param {String[]} prefixes
*/
rememberPrefixes: function (prefixes) {
var me = this;
if (!me.downloadedPrefixes) {
me.downloadedPrefixes = sol.create("sol.common.Cache");
}
if (me.downloadedPrefixes) {
prefixes.forEach(function (prefix) {
me.downloadedPrefixes.put(String(prefix), true);
});
}
},
/**
* Get a translation for a key by a given language code.
*
* sol.common.TranslationTerms.getTerm('de', sol.contract.ix.client');
*
* @param {String|de.elo.ix.client.ClientInfo} language Either an ISO language String, or an de.elo.ix.client.ClientInfo Object
* @param {String} key The key in the resource files
* @param {boolean} requestedTerm (optional) if not set, function requests term if not in list.
* @return {String} result The value of the key
*/
getTerm: function (language, key, requestedTerm) {
var me = this,
result;
if (language instanceof ClientInfo) {
language = language.language;
}
if (!language) {
me.logger.warn("Language not set.");
return key;
}
if (!me.translateTerms) {
me.require();
}
if (!me.translateTerms.containsKey(language)) {
me.translateTerms.put(language, sol.create("sol.common.Cache"));
}
result = me.translateTerms.get(language).get(key);
if (!result) {
if (!requestedTerm) {
me.logger.debug("Translation key not found or cached. requesting key: " + key + ". This could be the case if used within templates. Please note that prefetching translation keys improves system performance.");
me.require(key, language);
return me.getTerm(language, key, true);
} else {
me.logger.warn("Translation key not found: " + key);
return key;
}
}
return result;
},
/**
* Translates a key to the current language
* @param {String} key The key in the resource files
* @return {String} result The translated key
*
*/
translate: function (key) {
var me = this,
language, _result;
me.logger.enter("translate", arguments);
if (ixConnect) {
language = ixConnect.loginResult.clientInfo.language;
} else {
throw "IX connection is not available.";
}
_result = String(me.getTerm(language, key));
me.logger.exit("translate", _result);
return _result;
}
});